#ifndef _MAP_HANDLER
#define _MAP_HANDLER

#define MAP_ERROR_NOT_ACTIVE		0
#define MAP_ERROR_TO_LOW			1
#define MAP_ERROR_NO_KEY			2
#define MAP_ERROR_NO_QUEST			3
#define MAP_ERROR_NO_ITEM			4
#define MAP_ERROR_WRONG_TYPE		5
#define MAP_ERROR_NONE				6

#define NORMAL_DISTANCE				200

class Object;
class Creature;
class GameObject;
class World;
class MapHandler;
class MapInterface;

class DLL_EXPORT MapCell
{
	friend class MapHandler;
	set<Object*> m_objects;
	MapHandler* m_pBelonging;
	void FindInRange(Object* obj);
	void SearchEnvironment(Object* obj);
	ui32 xid, yid;
};

class DLL_EXPORT MapHandler : public CThread, public EventWorker
{
	friend class World;
	friend class MiscManager;
	friend class MapCell;
	bool display;
	WorldMapInfo* m_mapinfo;
	set<Object*> m_activeobjects;
	set<Object*> m_insertobjects;
	set<Object*> m_updateobjects;
	boost::unordered_set<Object*> m_staticgos;
	void ProcessUpdates();
	Mutex m_objectlock;
	ui32 m_crguids;
	ui32 m_objguids;
	ui32 m_mapid;
	void LoadCreatures();
	void LoadGameObjects();
	void SearchEnvironment(Object* obj, ui32 x, ui32 y);
	MapCell*** cells;
	TerrainHandler* m_terrainhandler;
	void UpdateCellObjects();
	ui32 m_lastupdate;
	void WorkHolders();
	ui32 m_reanimationcount;
	ui32 m_lastobjectupdate;
	MapInterface* m_mapinterface;
#ifdef WIN32
	DWORD m_pid;
#endif
public:
	MapHandler(WorldMapInfo* inf, ui32 mapid);
	void Loop();
	ui8 CheckAdd(Object* obj, void* misc);
	void AddObject(Object* obj);
	void RemoveObject(Object* obj);
	Creature* CreateCreature(ui32 entry);
	GameObject* CreateGameObject(ui32 entry);
	Creature* GetCreature(ui64 guid);
	GameObject* GetGameObject(ui64 guid);
	void AddUpdateObject(Object* obj);
	void UpdateMapCell(Object* obj);
	void UpdateSet(Object* obj);
	MapInterface* GetMapInterface() { return m_mapinterface; }
	float GetLandHeight(float x, float y)
	{
		return m_terrainhandler->GetLandHeight(x, y);
	}
	ui16 GetAreaId(float x, float y)
	{
		return m_terrainhandler->GetAreaId(x, y);
	}

	ui32 GetMapId() { return m_mapid; }
	
	//	Never call this function manually! Should only be called after MSG_MOVE_TELEPORT_ACK
	//	to resend the creationdata to the client!
	void RebuildAfterAck(Object* obj);

	//	NERVER, NEVER, NEVER, NEVER try to call this function from outside!! (it actually wont work :P)
	void TryReanimate();
};

#endif